#pragma once

#if USE_VULKAN

#include <vulkan/vulkan.h>
#include <vector>
#include <optional>

namespace vkinfer
{

#define VK_CHECK_RESULT(f)                                                               \
{                                                                                        \
    VkResult res = (f);                                                                  \
    if (res != VK_SUCCESS)                                                               \
    {                                                                                    \
        printf("Fatal : VkResult is %d in %s at line %d\n", res,  __FILE__, __LINE__);   \
    }                                                                                    \
}

    struct QueueFamilyIndices 
    {
        std::optional<uint32_t> compute_family;
        std::optional<uint32_t> transfer_family;

        bool isComplete() 
        {
            return compute_family.has_value() && transfer_family.has_value();
        }
    };

    QueueFamilyIndices find_queue_families(VkPhysicalDevice device);
    bool is_device_suitable(VkPhysicalDevice device);

    uint32_t* read_shader_file(uint32_t& length, const char* filename);

    uint32_t find_memory_type(VkPhysicalDevice device, uint32_t memoryTypeBits,
        VkMemoryPropertyFlags properties);
    void create_buffer(VkPhysicalDevice physicalDevice, VkDevice device,
        VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties,
        VkBuffer& buffer, VkDeviceMemory& bufferMemory);
    void copy_buffer(VkDevice device, VkCommandPool commandPool, VkQueue queue,
        VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size);
}

#endif
